package com.qf.common.base.handler;

import cn.hutool.core.util.ReflectUtil;

import com.qf.common.base.dto.ArgsErrorInfo;
import com.qf.common.base.ex.*;
import com.qf.common.base.result.ResponseResult;
import com.qf.common.base.result.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhangwei
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ResponseResult<Object> handlerException(Exception ex) {
        ex.printStackTrace();
        log.error("错误的信息:{}", ex.getMessage());
        return ResponseResult.error();
    }

    @ExceptionHandler(ControllerException.class)
    public ResponseResult<Object> handlerException(ControllerException ex){
        ex.printStackTrace();
        log.error("错误的信息:{}", ex.getMessage());
        return ResponseResult.error(ex.getResultStatus());
    }@ExceptionHandler(ServiceException.class)
    public ResponseResult<Object> handlerException(ServiceException ex){
        ex.printStackTrace();
        log.error("错误的信息:{}", ex.getMessage());
        return ResponseResult.error(ex.getResultStatus());
    }
    @ExceptionHandler(PhoneCodeException.class)
    public ResponseResult<Object> phoneCoderException(PhoneCodeException ex){
        ex.printStackTrace();
        log.error("错误的信息:{}", ex.getMessage());
        return ResponseResult.error(ex.getResultStatus());
    }
    @ExceptionHandler(AuditException.class)
    public ResponseResult<Object> AuditException(AuditException ex) {
        ex.printStackTrace();
        log.info("错误信息为:{}", ex.getMessage());
        return ResponseResult.error(ex.getResultStatus());
    }
    @ExceptionHandler(UnauthorizedException.class)
    public ResponseResult<Object> UnauthorizedException(UnauthorizedException ex){
        ex.printStackTrace();
        log.error("错误的信息:{}", ResultStatus.NOT_AUTHORIZED);
        return ResponseResult.error(ResultStatus.NOT_AUTHORIZED);
    }


    @ExceptionHandler(BaseException.class)
    public ResponseResult<Object> handlerException(BaseException ex) {
        ex.printStackTrace();
        return ResponseResult.error(ex.getResultStatus());
    }

    /**
     * 属性名  错误信息
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseResult<List<ArgsErrorInfo>> handlerException(ConstraintViolationException ex) {
        ex.printStackTrace();
        return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getConstraintViolations().stream().map(violation -> {
            List<Path.Node> nodeList = (List<Path.Node>) ReflectUtil.getFieldValue(violation.getPropertyPath(), "nodeList");
            return ArgsErrorInfo.builder().filedName(nodeList.get(nodeList.size() - 1).getName()).errorMessage(violation.getMessage()).build();
        }).collect(Collectors.toList()));
    }

    /**
     * message
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ResponseResult<List<ArgsErrorInfo>> handlerException(BindException ex) {
        ex.printStackTrace();
        return ResponseResult.error(ResultStatus.ARGS_VALID_ERROR, ex.getBindingResult().getFieldErrors().stream().map(fieldError ->
                ArgsErrorInfo.builder().filedName(fieldError.getField()).errorMessage(fieldError.getDefaultMessage()).build()).collect(Collectors.toList()));
    }

    @ExceptionHandler(value = DataAccessException.class)
    // @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public ResponseResult<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        ex.printStackTrace();
        log.info("错误信息为:{}", ex.getMessage());
        //匹配SQL错误中的实体重复错误    Duplicate entry "xiaoma" ....
        if(ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" ");//空格分隔
            String msg = split[2]+"已存在";
            return ResponseResult.error(ResultStatus.DOES__EXIST);
        }
        //在前端或者客户端返回友好提示
        return ResponseResult.error(ResultStatus.DOES__EXIST);
    }




}
